/*
 * @Date         : 2024-05-17 15:42:14 星期5
 * @Author       : xut
 * @Description  :
 */
import { resolve } from "node:path"
import * as grpc from "@grpc/grpc-js"
import * as protoLoader from "@grpc/proto-loader"
import { ProtoGrpcType } from "../pb/index.services"
import { envConfig } from "./config/default"
import { connectDB } from "./utils/prisma"
import { authenticateInterceptor } from "./interceptor/authentication.interceptor"

import { AuthServiceHandlers } from "../pb/auth/AuthService"
import {
  registerHandler,
  loginHandler,
  refreshAccessTokenHandler,
  verifyEmailHandler,
} from "./controllers/auth.controller"

import { PostServiceHandlers } from "../pb/post/PostService"
import {
  createPostHandler,
  updatePostHandler,
  deletePostHandler,
  findPostHandler,
  findAllPostsHandler,
} from "./controllers/post.controller"

import { UserServiceHandlers } from "../pb/user/UserService"
import {
  updateUserHandler,
  DeleteUserHandler,
  getUserHandler,
  litsUsersHandler,
} from "./controllers/user.controller"

const protoLoadOptions: protoLoader.Options = {
  keepCase: true,
  longs: String,
  enums: String,
  defaults: true,
  oneofs: true,
}

const PORT = envConfig.port
const PROTO_FILE = "../proto/index.services.proto"
const packageDef = protoLoader.loadSync(
  resolve(__dirname, PROTO_FILE),
  protoLoadOptions
)
const proto = grpc.loadPackageDefinition(packageDef) as unknown as ProtoGrpcType
const authPackage = proto.auth
const userPackage = proto.user
const postPackage = proto.post

const server = new grpc.Server({ interceptors: [authenticateInterceptor] })

server.addService(authPackage.AuthService.service, {
  SignUpUser: (call, cb) => registerHandler(call, cb),
  SignInUser: (req, res) => loginHandler(req, res),
  RefreshToken: (req, res) => refreshAccessTokenHandler(req, res),
  VerifyEmail: (req, res) => verifyEmailHandler(req, res),
} as AuthServiceHandlers)

server.addService(userPackage.UserService.service, {
  ListUsers: (call) => litsUsersHandler(call),
  GetUser: (req, res) => getUserHandler(req, res),
  UpdateUser: (req, res) => updateUserHandler(req, res),
  DeleteUser: (req, res) => DeleteUserHandler(req, res),
} as UserServiceHandlers)

server.addService(postPackage.PostService.service, {
  ListPosts: (call) => findAllPostsHandler(call),
  GetPost: (req, res) => findPostHandler(req, res),
  CreatePost: (req, res) => createPostHandler(req, res),
  UpdatePost: (req, res) => updatePostHandler(req, res),
  DeletePost: (req, res) => deletePostHandler(req, res),
} as PostServiceHandlers)

server.bindAsync(
  `localhost:${PORT}`,
  grpc.ServerCredentials.createInsecure(),
  (err, port) => {
    if (err) {
      console.error(err)
      return
    }

    connectDB()
    console.log(`grpc Server listening on localhost:${port}`)
  }
)
